//
// Created by gavin on 2017/1/20.
//

#include "ScanFiles.h"
#include "DzLog.h"



#include <sys/stat.h>
#include <dirent.h>
#include <unistd.h>


#include <string.h>
#include <errno.h>
static ScanFiles *scanFiles = NULL;

#undef  LOG_TAG
#define LOG_TAG "ScanFile"

ScanFiles::ScanFiles(){

}

ScanFiles *ScanFiles::getInterface() {
    if (scanFiles == NULL) {
        scanFiles = new ScanFiles();
    }
    return scanFiles;
}

int ScanFiles::init(const char * path, list<string> fileType) {
    uninitScanFileType();
    initScanFileType(fileType);

    LOGE("Scarn being");
    scanPath(path);
    LOGE("Scarn finsh");

    return 0;
}

void ScanFiles::initScanFileType(list<string> fileType) {
    list<string>::iterator it;
    for (it=fileType.begin();it!=fileType.end();it++){
        addFileTypeFilter((*it).c_str());
    }
}

void ScanFiles::uninitScanFileType() {
    list<FilesData *>::iterator it;
    for (it=filesData.begin();it!=filesData.end();it++) {
        (*it)->fileList.clear();
        delete((*it));
    }
    filesData.clear();
}

/**
 * 添加文件识别类型
 */
void ScanFiles::addFileTypeFilter(const char * fileType) {
    FilesData *filesDataTmp = new FilesData();
    filesDataTmp->fileType= fileType;
    filesDataTmp->fileList.clear();
    filesData.push_back(filesDataTmp);
}

int ScanFiles::scanPath(const char *dir){
    struct stat statbuf;
    struct dirent *dirp = NULL;
    DIR *dp = NULL;
    char *ptr = NULL;
    char path[1024] = "";

    if (dir == NULL) {
        return 0;
    }

    strcpy(path, dir);
    memset(&statbuf, 0, sizeof(struct stat));

    if(lstat(path,&statbuf) < 0){
        LOGE("lstat is error %s",strerror(errno));
        return 0;
    }

    if(S_ISDIR(statbuf.st_mode) == 0){	//is a dir
        return 0;
    }

    if((dp = opendir(path)) == NULL){
        LOGE("opendir is error %s \n",strerror(errno));
        return 0;
    }

    if (strlen(path) > 516) {
        return 0;
    }

    ptr = path + strlen(path);
    *ptr++ = '/';
    *ptr = 0;
    while((dirp = readdir(dp)) != 0){
        if (strlen(dirp->d_name) < 516) {
            strcpy(ptr,dirp->d_name);
        } else {
            return 0;
        }
        // d_type：8-文件，4-目录
        if(dirp->d_type == 8) {
            fileFilter(dirp->d_name);
        } else {
            if(strcmp(dirp->d_name,".") == 0 || strcmp(dirp->d_name,"..") == 0)
                continue;
            if(scanPath(path) != 0)  //使用递归层级查找所有当前目录下以及当前目录下胡目录下存在的同名文件
                break;
        }
    }
    closedir(dp);
    return 0;
}

list<string> *ScanFiles::getFileTypeList(const char * fileType){
    list<string> * ret= NULL;
    list<FilesData *>::iterator it;
    for (it=filesData.begin();it!=filesData.end();it++){
        if (strcmp((*it)->fileType.c_str(), fileType) == 0) {
            return &(*it)->fileList;
        }
    }
    return NULL;
}

/*
 * 输出扫描的文件类型以及文件log
 */
void ScanFiles::printScanFiles() {
    list<FilesData *>::iterator it;
    for (it=filesData.begin();it!=filesData.end();it++){
        list<string>::iterator fileName;
        for (fileName=(*it)->fileList.begin();fileName!=(*it)->fileList.end();fileName++){
            LOGD("type:%s, %s", (*it)->fileType.c_str(), (*fileName).c_str());
        }
    }
}

/**
 * 文件筛选，把文件加到对应的文件列表中
 */
int ScanFiles::fileFilter(const char* fileName) {

    if (fileName == NULL) {
        return -1;
    }

    list<FilesData *>::iterator it;
    for (it=filesData.begin();it!=filesData.end();it++) {
        if (strlen(fileName) <= (*it)->fileType.length()) {
            return -1;
        }
        //获取文件拓展名
        const char *fileNameExtension = fileName + (strlen(fileName)-(*it)->fileType.length());
        if (strcmp(fileNameExtension, (*it)->fileType.c_str())== 0){
            (*it)->fileList.push_back(fileName);
        }
    }

    return 0;
}